﻿using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using Stylet;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using WriteBugs.Controls;
using WriteBugs.Library.Model;
using WriteBugs.Library.Utils;

namespace WriteBugs.Pages
{
    public class MainViewModel : Screen
    {
        private readonly IWindowManager _windowManager;
        private readonly IViewFactory _viewFactory;

        public MainViewModel(IWindowManager windowManager, IViewFactory viewFactory)
        {
            _windowManager = windowManager;
            _viewFactory = viewFactory;
        }

        private readonly string LocDataPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Excerpt.bin");
        private readonly string SampleTxtPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sample.txt");

        private Excerpt RootExcerpt = null;
        private Excerpt CurrentCatalog { get; set; } = null;
        public Excerpt CurrentContent { get; set; } = null;
        public string? CurrentContentTitle { get; set; }

        public TreeViewAdvNodeItem? TreeViewAdvNodeItems { get; set; }
        public TreeViewAdvNodeItem? SelectedTreeViewAdvNodeItem { get; set; }

        public BindableCollection<ListViewAdvNodeItem>? ListViewAdvNodeItems { get; set; }
        public ListViewAdvNodeItem? SelectedListViewAdvNodeItem { get; set; }

        public string SearchText { get; set; } = string.Empty;

        public string CodeEditorText { get; set; } = string.Empty;
        public string InputCodeText { get; set; } = string.Empty;
        public string RunResult { get; set; } = string.Empty;

        #region 初始化
        protected override void OnViewLoaded()
        {
            base.OnViewLoaded();

            LoadRootExcerpt();
            LoadTreeView();
            CurrentCatalog = RootExcerpt;

            IsShowTree = AppSettings.Default.IsShowTree;
            if (IsShowTree)
            {
                LeftTreeViewShowClick();
            }
            else
            {
                LeftTreeViewHideClick();
            }

            IsShowAllExcerpt = AppSettings.Default.IsShowAllExcerpt;
            ReflahListViewAdv();

            IsShowDebug = AppSettings.Default.IsShowDebug;

            this.Bind(s => SearchText, (o, e) => SearchTextChanged());
            this.Bind(s => CurrentContentTitle, (o, e) => CurrentContentTitleChanged());
            this.Bind(s => InputCodeText, (o, e) => InputCodeTextChanged());

            StartSavingTask();

            DebugConsloeWriter debugConsloeWriter = new DebugConsloeWriter();
            debugConsloeWriter.WriteMessage += DebugConsloeWriter_WriteMessage;
            Console.SetOut(debugConsloeWriter);
        }

        private void DebugConsloeWriter_WriteMessage(ConsoleWiiteEventArgs args)
        {
            RunResult += args.value;
        }

        private void LoadRootExcerpt()
        {
            try
            {
                var data = File.ReadAllBytes(LocDataPath);
                RootExcerpt = (Excerpt)ConvertHelper.Bytes2Object(data);
            }
            catch
            {
                RootExcerpt = new Excerpt
                {
                    ExcerptType = ExcerptType.Catalog,
                    Title = "Bugs",
                };

                Excerpt excerpt = new Excerpt()
                {
                    ExcerptType = ExcerptType.Content,
                    Title = "使用说明",
                    Code = File.ReadAllText(SampleTxtPath),
                    Parent = RootExcerpt,
                };

                RootExcerpt.Childen.Add(excerpt);
            }
        }

        private void LoadTreeView()
        {
            TreeViewAdvNodeItem? Items = CreatTreeViewAdvNodeItemFromExcerptList(RootExcerpt);
            TreeViewAdvNodeItems = Items;
        }

        private TreeViewAdvNodeItem? CreatTreeViewAdvNodeItemFromExcerptList(Excerpt excerpt)
        {
            if (excerpt != null && excerpt.ExcerptType == ExcerptType.Catalog)
            {
                TreeViewAdvNodeItem treeNodes = new TreeViewAdvNodeItem
                {
                    Excerpt = excerpt,
                };

                foreach (var child in excerpt.Childen)
                {
                    var treenode = CreatTreeViewAdvNodeItemFromExcerptList(child);
                    if (treenode != null)
                    {
                        treeNodes.Children.Add(treenode);
                    }
                }

                return treeNodes;
            }

            return null;
        }
        #endregion

        #region 保存
        private bool IsDuty = false;
        private readonly ManualResetEvent SaveManualResetEvent = new ManualResetEvent(false);

        private void StartSavingTask()
        {
            Task.Run(() =>
            {
                SaveManualResetEvent.Reset();
                while (true)
                {
                    if (SaveManualResetEvent.WaitOne(5000))
                    {
                        break;
                    }

                    if (IsDuty)
                    {
                        try
                        {
                            Save();
                        }
                        finally
                        {
                            IsDuty = false;
                        }
                    }
                }
            });
        }

        protected override void OnClose()
        {
            base.OnClose();

            AppSettings.Default.IsShowTree = IsShowTree;
            AppSettings.Default.IsShowAllExcerpt = IsShowAllExcerpt;
            AppSettings.Default.IsShowDebug = IsShowDebug;
            AppSettings.Default.Save();

            IsDuty = false;
            SaveManualResetEvent.Set();
            Save();
        }

        private void Save()
        {
            Debug.WriteLine($"Save");

            byte[] bytes = ConvertHelper.Object2Bytes(RootExcerpt);
            File.WriteAllBytes(LocDataPath, bytes);
        }

        #endregion

        #region  基础操作：新增目录、新增随笔、显示全部

        private bool IsShowAllExcerpt { get; set; }

        public bool CanAddFolder => IsShowTree;
        public bool CanAddExcerpt => CurrentCatalog != null;

        public void AddFolder()
        {
            if (CurrentCatalog != null)
            {
                Excerpt excerpt = new Excerpt
                {
                    Title = "New Folder",
                    ExcerptType = ExcerptType.Catalog,
                    Parent = CurrentCatalog,
                    LastUpdateTime = DateTime.Now,
                };

                CurrentCatalog.Childen.Add(excerpt);

                LoadTreeView();
                ShowExcerptsByCatalog(CurrentCatalog);
                IsDuty = true;
            }
        }

        public void AddExcerpt()
        {
            if (CurrentCatalog != null)
            {
                Excerpt excerpt = new Excerpt
                {
                    Title = "New Content",
                    ExcerptType = ExcerptType.Content,
                    Parent = CurrentCatalog,
                    LastUpdateTime = DateTime.Now,
                };
                CurrentCatalog.Childen.Add(excerpt);

                ReflahListViewAdv();
            }
            IsDuty = true;
        }

        private void ReflahListViewAdv()
        {
            if (IsShowAllExcerpt)
            {
                ShowAllExcerpts();
            }
            else
            {
                ShowExcerptsByCatalog(CurrentCatalog);
            }
        }

        public void ShowAllExcerpts()
        {
            ListViewAdvNodeItems = new BindableCollection<ListViewAdvNodeItem>(QueryAllExcerpts(null));
            IsShowAllExcerpt = true;
        }

        private void ShowExcerptsByCatalog(Excerpt? excerpt)
        {
            List<ListViewAdvNodeItem> Items = new List<ListViewAdvNodeItem>();
            if (excerpt != null)
            {
                foreach (var child in excerpt.Childen)
                {
                    Items.Add(new ListViewAdvNodeItem
                    {
                        Excerpt = child,
                    });
                }
            }
            ListViewAdvNodeItems = new BindableCollection<ListViewAdvNodeItem>(Items);

            SelectedListViewAdvNodeItem = null;
            CurrentContent = null;
            listViewAdv_SelectedItemChanged();

            IsShowAllExcerpt = false;
        }

        public void About()
        {
            _windowManager.ShowMessageBox("Write by:seabluescn@163.com","About", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        #endregion

        #region 选择、删除

        public void leftTreeView_SelectedItemChanged()
        {
            //Debug.WriteLine($"leftTreeView_SelectedItemChanged:{SelectedTreeViewAdvNodeItem?.Title}");

            if (SelectedTreeViewAdvNodeItem != null)
            {
                CurrentCatalog = SelectedTreeViewAdvNodeItem.Excerpt;
                ShowExcerptsByCatalog(CurrentCatalog);
            }
        }

        public void listViewAdv_SelectedItemChanged()
        {
            //Debug.WriteLine($"listViewAdv_SelectedItemChanged:{SelectedListViewAdvNodeItem?.Title}");

            if (SelectedListViewAdvNodeItem != null)
            {
                CurrentContent = SelectedListViewAdvNodeItem.Excerpt;
                CurrentContentTitle = CurrentContent?.Title;
                CodeEditorText = CurrentContent?.Code;
            }
            else
            {
                CurrentContent = null;
                CurrentContentTitle = string.Empty;
                CodeEditorText = String.Empty;
            }
        }

        public void listViewAdv_DoubleClick()
        {
            if (SelectedListViewAdvNodeItem != null &&
                SelectedListViewAdvNodeItem.Excerpt != null &&
                SelectedListViewAdvNodeItem.Excerpt.ExcerptType == ExcerptType.Catalog)
            {
                CurrentCatalog = SelectedListViewAdvNodeItem.Excerpt;
                ShowExcerptsByCatalog(CurrentCatalog);
            }
        }

        public void BackToUp()
        {
            Debug.WriteLine("BackToUp");
            CurrentCatalog = CurrentCatalog.Parent;
            ShowExcerptsByCatalog(CurrentCatalog);
        }
        public bool CanBackToUp => CurrentCatalog != null && CurrentCatalog != RootExcerpt;

        public void listViewAdv_ItemDeleted()
        {
            if (CurrentCatalog != null && CurrentContent != null)
            {
                string et = CurrentContent.ExcerptType == ExcerptType.Catalog ? "目录" : "随笔";
                if (MessageBox.Show($"确实要删除{et }:{CurrentContent.Title}吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    RemoveExcerptFromChildren(CurrentCatalog, CurrentContent);
                    if (CurrentContent.ExcerptType == ExcerptType.Catalog)
                    {
                        LoadTreeView();
                    }

                    ReflahListViewAdv();
                }
            }
        }

        private void RemoveExcerptFromChildren(Excerpt father, Excerpt excerpt)
        {
            foreach (var child in father.Childen)
            {
                if (child == excerpt)
                {
                    father.Childen.Remove(child);
                    break;
                }
                else
                {
                    RemoveExcerptFromChildren(child, excerpt);
                }
            }
        }

        #endregion

        #region 搜索
        private void SearchTextChanged()
        {
            if (SearchText != string.Empty)
            {
                List<ListViewAdvNodeItem> excerpts = QueryAllExcerpts(SearchText);
                ListViewAdvNodeItems = new BindableCollection<ListViewAdvNodeItem>(excerpts);
            }
            else
            {
                ReflahListViewAdv();
            }
        }

        private List<ListViewAdvNodeItem> QueryAllExcerpts(string? key)
        {
            List<ListViewAdvNodeItem> excerpts = new List<ListViewAdvNodeItem>();
            QueryListFromExcerpt(excerpts, RootExcerpt, key);
            excerpts.Sort();
            return excerpts;
        }

        private void QueryListFromExcerpt(List<ListViewAdvNodeItem> list, Excerpt excerpt, string? key)
        {
            if (excerpt != null)
            {
                if (excerpt.ExcerptType == ExcerptType.Content)
                {
                    if (key == null)
                    {
                        list.Add(new ListViewAdvNodeItem
                        {
                            Excerpt = excerpt,
                        });
                    }
                    else
                    {
                        if (excerpt.Title.Contains(key, StringComparison.OrdinalIgnoreCase))
                        {
                            list.Add(new ListViewAdvNodeItem
                            {
                                Excerpt = excerpt,
                            });
                        }
                    }
                }
                else
                {
                    foreach (var child in excerpt.Childen)
                    {
                        QueryListFromExcerpt(list, child, key);
                    }
                }
            }
        }

        #endregion

        #region 编辑、运行
        private void CurrentContentTitleChanged()
        {
            if (CurrentContent != null && ListViewAdvNodeItems != null)
            {
                if (CurrentContent.Title != CurrentContentTitle)
                {
                    CurrentContent.Title = CurrentContentTitle;
                    CurrentContent.LastUpdateTime = DateTime.Now;

                    if (CurrentContent.ExcerptType == ExcerptType.Catalog)
                    {
                        LoadTreeView();
                    }
                    ListViewAdvNodeItems?.Refresh();

                    IsDuty = true;
                }
            }
        }

        private void InputCodeTextChanged()
        {
            if (CurrentContent != null && CurrentContent.Code != InputCodeText)
            {
                CurrentContent.Code = InputCodeText;
                CurrentContent.LastUpdateTime = DateTime.Now;
                NotifyOfPropertyChange(nameof(CanRun));

                ListViewAdvNodeItems?.Refresh();
                IsDuty = true;
            }
        }

        public void Run()
        {
            string timestr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            try
            {
                RunResult = $"[{timestr}]:Compile Success\r\n";
                var script = CSharpScript.Create(InputCodeText);
                script.RunAsync();
            }
            catch (CompilationErrorException ex)
            {
                RunResult = $"[{timestr}]:Compile Error!\r\n{ex.Message}";
            }
            catch (Exception ex)
            {
                RunResult = $"[{timestr}]:异常!\r\n{ex.Message}";
            }

            IsShowDebug = true;
        }

        public bool CanRun => CurrentContent != null && !string.IsNullOrEmpty(CurrentContent.Code);

        #endregion

        #region 界面控制

        #region  左侧树显示/隐藏
        public bool IsShowTree { get; set; } = false;
        public Visibility LeftTreeViewVisibility { get; set; } = Visibility.Collapsed;

        public void ShowOrHideTree()
        {
            if (IsShowTree)
            {
                LeftTreeViewHideClick();
            }
            else
            {
                LeftTreeViewShowClick();
            }
        }

        private void LeftTreeViewHideClick()
        {
            LeftTreeViewVisibility = Visibility.Collapsed;
            IsShowTree = false;
        }

        private void LeftTreeViewShowClick()
        {
            LeftTreeViewVisibility = Visibility.Visible;
            IsShowTree = true;
        }
        #endregion

        #region 编辑界面
        private bool IsShowEditor => CurrentContent != null && CurrentContent.ExcerptType == ExcerptType.Content;
        public Visibility EditorVisibility => IsShowEditor ? Visibility.Visible : Visibility.Collapsed;
        public Visibility NoPreviewVisibility => IsShowEditor ? Visibility.Collapsed : Visibility.Visible;

        #endregion

        #region Debug界面
        public bool IsShowDebug { get; set; } = true;
        public Visibility DebugPanelVisibility => IsShowDebug ? Visibility.Visible : Visibility.Collapsed;

        public void Ding()
        {
            IsShowDebug = !IsShowDebug;
        }

        public void HideDebug()
        {
            IsShowDebug = false;
        }


        #endregion

        #endregion

        #region 拖动

        public DragInfo? TreeViewDragInfo { get; set; }

        public void TreeViewAdvDragged()
        {
            //Debug.WriteLine($"Dragged:{TreeViewDragInfo?.SourceExcerpt?.Title} to {TreeViewDragInfo?.TargetExcerpt?.Title}");

            var fromExcerpt = TreeViewDragInfo?.SourceExcerpt;
            var toExcerpt = TreeViewDragInfo?.TargetExcerpt;
            MoveToCatalog(fromExcerpt, toExcerpt);
        }

        public bool ListViewCanStartDrag => !IsShowAllExcerpt;
        public DragInfo? ListViewDragInfo { get; set; }

        public void ListViewAdvDragged()
        {
            if (ListViewDragInfo != null)
            {
                if (ListViewDragInfo.DragType == DragType.SourceToTarget)
                {
                    //Debug.WriteLine($"Dragged:{ListViewDragInfo?.SourceExcerpt.Title} to {ListViewDragInfo.TargetExcerpt?.Title}");
                    var fromExcerpt = ListViewDragInfo.SourceExcerpt;
                    var toExcerpt = ListViewDragInfo.TargetExcerpt;
                    MoveToCatalog(fromExcerpt, toExcerpt);
                    return;
                }

                if (ListViewDragInfo?.DragType == DragType.SourceMove)
                {
                    //Debug.WriteLine($"Dragged:{ListViewDragInfo.SourceExcerpt?.Title} move to {ListViewDragInfo.MoveToIndex}");
                    MoveIndex(ListViewDragInfo.SourceExcerpt, ListViewDragInfo.MoveToIndex);
                    return;
                }
            }
        }

        private void MoveToCatalog(Excerpt? fromExcerpt, Excerpt? toExcerpt)
        {
            if (fromExcerpt != null && toExcerpt != null && fromExcerpt.Parent != null
                && fromExcerpt != toExcerpt)
            {
                fromExcerpt.Parent.Childen.Remove(fromExcerpt);
                toExcerpt.Childen.Add(fromExcerpt);
                fromExcerpt.Parent = toExcerpt;

                LoadTreeView();
                ShowExcerptsByCatalog(CurrentCatalog);

                IsDuty = true;
            }
        }

        private void MoveIndex(Excerpt? fromExcerpt, int newIndex)
        {
            if (fromExcerpt != null && fromExcerpt.Parent != null)
            {
                int count = fromExcerpt.Parent.Childen.Count;
                if (newIndex >= count) newIndex = count - 1;

                int old_index = fromExcerpt.Parent.Childen.IndexOf(fromExcerpt);

                if (newIndex != old_index)
                {
                    fromExcerpt.Parent.Childen.Move(old_index, newIndex);

                    if (fromExcerpt.ExcerptType == ExcerptType.Catalog)
                    {
                        LoadTreeView();
                    }
                    ShowExcerptsByCatalog(CurrentCatalog);

                    IsDuty = true;
                }
            }
        }

        #endregion
    }
}
